home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / libdwarf / dwarf_addr_finder.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  16.3 KB  |  698 lines

  1. /*
  2.     dwarf_addr_finder.c
  3.     $Source: /cmplrs.src/v4.00/libdwarf/RCS/dwarf_addr_finder.c,v $
  4.     $Date: 1994/06/17 02:38:58 $
  5.  
  6.     This function make it possible to fix up addresses in
  7.     dwarf, such as is needed by rqs.   The method: for each
  8.     address in dwarf, it calls a callback-function,
  9.     passing a section number and the offset-in-the-section
  10.     of the address and the present value of the addr at that
  11.     offset and the size, in bytes, of an address.
  12.     The size will be identical for all callbacks, of course!
  13.  
  14.     This only finds addresses actually marked as such. addresses
  15.     hidden in constants are NOT noticed.
  16.  
  17.     This is presumed to be running against an a.out or dso and
  18.     it does not rely on relocation information (no such information
  19.     exists for the dwarf sections in an a.out or dso).
  20.  
  21.     The implementor of the callback-function then
  22.     does whatever is needed with that address.
  23.       rqs, for example, will modify the section data to update
  24.       the address.
  25.     
  26.  
  27.     User Interface:
  28.  
  29.     int dwarf_addr_finder(Elf * elf_file_ptr,
  30.         Dwarf_addr_callback_func cb_func,
  31.         int *dwerr);
  32.     It returns
  33.         DW_DLV_OK if it succeeds(all callbacks have been done).
  34.         DW_DLV_ERROR if there was an error (and sets the
  35.             error pointer (see the dwarf Consumer doc
  36.             for information on handling that).
  37.         DW_DLV_NO_ENTRY if there is no dwarf data present.
  38.     *dwerr may be set to a dwarf error code if there is one known.
  39.     Or it may be set to -1 (some other error).
  40.  
  41.      The caller must pass a valid open Elf * elf file pointer.
  42.     If there is an error, the dwerr parameter is used to put the libdwarf
  43.     error code in the int pointed at.
  44.  
  45.  
  46.     The callback Function (whose address is
  47.     passed in the 'func' arg above) is implemented by the user as:
  48.  
  49.     int cb_func( int section, Dwarf_Off secoff, Dwarf_Addr existingAddr,
  50.         int addrsize) { ...do whatever... return DW_DLV_OK;}
  51.  
  52.     The callback function should return one of the following to
  53.     its caller:
  54.         DW_DLV_OK meaning all is ok, continue.
  55.          DW_DLV_ERROR meaning that the called-back function
  56.         detected something wrong: abort the entire process
  57.         and return immediately from dwarf_addr_finder, returning,
  58.         from there, DW_DLV_ERROR.
  59.  
  60.  
  61.     Obviously you may choose any name: there is nothing
  62.     special about cb_func!
  63.     
  64.             
  65.  
  66. */
  67. #include <libelf.h>
  68. #include <dwarf.h>
  69. #include <libdwarf.h>
  70. #include "dwarf_opaque.h"
  71. #include "dwarf_arange.h"
  72. #include "dwarf_line.h"
  73. #include "dwarf_frame.h"
  74. #include "dwarf_addr_finder.h"
  75. #include "dwarf_error.h"
  76.  
  77. typedef unsigned long long ull;
  78.  
  79. static int do_this_die_and_dealloc(Dwarf_Debug dbg,Dwarf_Die die,int *errval);
  80. static int 
  81. handle_debug_info(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval);
  82. static int 
  83. handle_debug_frame(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval);
  84. static int 
  85. handle_debug_aranges(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval);
  86. static int 
  87. handle_debug_line(Dwarf_Debug dbg,Dwarf_Die cu_die,Dwarf_addr_callback_func cb_func,int *errval);
  88. static int 
  89. handle_debug_loc(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval);
  90.  
  91. /* The ELF section numbers need to be gotten from libdwarf to be put here 
  92.    so the callback can get the section number
  93. */
  94. static int die_section_number;
  95. static int frame_section_number;
  96. static int aranges_section_number;
  97. static int line_section_number;
  98.  
  99. Dwarf_addr_callback_func send_addr_note;
  100.  
  101. int
  102. _dwarf_addr_finder(Elf * elf_file_ptr,
  103.                 Dwarf_addr_callback_func cb_func,
  104.                 int *dwerr)
  105. {
  106.  
  107.     Dwarf_Unsigned fin;
  108.     Dwarf_Error err = 0;
  109.     Dwarf_Debug dbg = 0;
  110.     int res = 0;
  111.     int errval = 0;
  112.     int sections_found = 0;
  113.  
  114.     res  = dwarf_elf_init(elf_file_ptr,DW_DLC_READ,/*errhand*/0,
  115.         /*errarg*/0,&dbg,&err);
  116.     if(res == DW_DLV_ERROR){
  117.         int errv = dwarf_errno(err);
  118.         return  errv;
  119.     }
  120.         if(res == DW_DLV_NO_ENTRY) {
  121.      return res;
  122.     }
  123.     
  124.     send_addr_note = cb_func;
  125.     
  126.     res = handle_debug_info(dbg,cb_func,&errval);
  127.     switch(res) {
  128.     case DW_DLV_OK:
  129.         ++sections_found;
  130.         break;
  131.     case DW_DLV_NO_ENTRY:
  132.         
  133.         break;
  134.     default:
  135.     case DW_DLV_ERROR:
  136.       dwarf_finish(dbg,&err);
  137.       *dwerr = errval;
  138.       return res; 
  139.     }
  140.  
  141.     res = handle_debug_aranges(dbg,cb_func,&errval);
  142.     switch(res) {
  143.     case DW_DLV_OK:
  144.         ++sections_found;
  145.         break;
  146.     case DW_DLV_NO_ENTRY:
  147.         break;
  148.     default:
  149.     case DW_DLV_ERROR:
  150.       dwarf_finish(dbg,&err);
  151.       *dwerr = errval;
  152.       return res; 
  153.     }
  154.     res = handle_debug_frame(dbg,cb_func,&errval);
  155.     switch(res) {
  156.     case DW_DLV_OK:
  157.         ++sections_found;
  158.         break;
  159.     case DW_DLV_NO_ENTRY:
  160.         break;
  161.     default:
  162.     case DW_DLV_ERROR:
  163.       dwarf_finish(dbg,&err);
  164.       *dwerr = errval;
  165.       return res; 
  166.     }
  167.  
  168.     res = handle_debug_loc(dbg,cb_func,&errval);
  169.     switch(res) {
  170.     case DW_DLV_OK:
  171.         ++sections_found;
  172.         break;
  173.     case DW_DLV_NO_ENTRY:
  174.         break;
  175.     default:
  176.     case DW_DLV_ERROR:
  177.       dwarf_finish(dbg,&err);
  178.       *dwerr = errval;
  179.       return res; 
  180.     }
  181.  
  182.     
  183.  
  184.     *dwerr = 0;
  185.     res =dwarf_finish(dbg,&err);
  186.     if(res == DW_DLV_ERROR) {
  187.         *dwerr = dwarf_errno(err);
  188.         return DW_DLV_ERROR;
  189.     }
  190.     if(sections_found == 0) {
  191.         return DW_DLV_NO_ENTRY;
  192.     }
  193.     return  DW_DLV_OK;
  194.  
  195. }
  196.  
  197. /*
  198.     Return DW_DLV_OK, ERROR, or NO_ENTRY.
  199. */
  200. static int 
  201. handle_debug_info(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval)
  202. {
  203.   Dwarf_Unsigned nxtoff = 1;
  204.   Dwarf_Unsigned curoff = 0; /* for calculating section-relative offsets */
  205.   Dwarf_Unsigned hdr_length;
  206.   Dwarf_Half     version_stamp;
  207.   Dwarf_Unsigned  abbrev_offset;
  208.   Dwarf_Half     addr_size;
  209.   Dwarf_Error err;
  210.   int terminate_now = 0;
  211.   int res = 0;
  212.   Dwarf_Die sibdie;
  213.   int sibres;
  214.   int nres = DW_DLV_OK;
  215.  
  216.  
  217.   for(
  218.       nres = dwarf_next_cu_header(dbg,&hdr_length,&version_stamp,
  219.         &abbrev_offset,
  220.         &addr_size,&nxtoff,&err)
  221.     ; terminate_now == 0 && nres == DW_DLV_OK  ;
  222.     curoff = nxtoff,
  223.         nres  = dwarf_next_cu_header(dbg,&hdr_length,&version_stamp,
  224.         &abbrev_offset,
  225.         &addr_size, &nxtoff, &err) 
  226.                                  ) {
  227.  
  228.     Dwarf_Die curdie = 0;
  229.     sibres = dwarf_siblingof(dbg,curdie,&sibdie,&err);
  230.         if(sibres == DW_DLV_OK) {
  231.       res = do_this_die_and_dealloc(dbg, curdie, errval);
  232.       switch(res) {
  233.       case DW_DLV_OK:
  234.         break;
  235.       case DW_DLV_NO_ENTRY:
  236.         break;
  237.       default:
  238.       case DW_DLV_ERROR:
  239.         return DW_DLV_ERROR;
  240.       }
  241.     }else  if(sibres == DW_DLV_ERROR) {
  242.         *errval = dwarf_errno(err);
  243.         return DW_DLV_ERROR;
  244.     }else {
  245.         /* NO ENTRY! */
  246.         /* impossible? */
  247.     }
  248.      
  249.   }
  250.   if(nres == DW_DLV_ERROR) {
  251.     Dwarf_Unsigned  localerr = dwarf_errno(err);
  252.     *errval = localerr;
  253.     return DW_DLV_ERROR;
  254.   }
  255.   return DW_DLV_OK;
  256. }
  257.  
  258. static int
  259. might_have_addr[] = {
  260. DW_AT_high_pc,
  261. DW_AT_low_pc,
  262. };
  263. static int
  264. might_have_locdesc[] = {
  265. DW_AT_segment,
  266. DW_AT_return_addr,
  267. DW_AT_frame_base,
  268. DW_AT_static_link,
  269. DW_AT_data_member_location,
  270. DW_AT_string_length,
  271. DW_AT_location,
  272. DW_AT_use_location,
  273. DW_AT_vtable_elem_location,
  274. };
  275.  
  276. /*
  277.     Return DW_DLV_OK if handling this went ok.
  278. */
  279. static int
  280. handle_attr_addr(Dwarf_Debug dbg,Dwarf_Die die,Dwarf_Half attrnum,
  281.     Dwarf_Error*perr)
  282. {
  283.     int res = DW_DLV_OK;
  284.     Dwarf_Off offset;
  285.     Dwarf_Addr addr;
  286.         Dwarf_Half form;
  287.         int ares;
  288.  
  289.     Dwarf_Attribute attr;
  290.         ares = dwarf_attr(die,attrnum,&attr,perr);
  291.         if(ares == DW_DLV_OK) {
  292.           int formres = dwarf_whatform(attr,&form,perr);
  293.           switch(formres) {
  294.           case DW_DLV_OK:
  295.             break;
  296.           case DW_DLV_ERROR:
  297.           case DW_DLV_NO_ENTRY: /* impossible. */
  298.           return formres;
  299.           
  300.           }
  301.        
  302.           switch(form) {
  303.           case DW_FORM_ref_addr:
  304.           case DW_FORM_addr:
  305.           res = dwarf_attr_offset(die,attr,&offset,perr);
  306.           if(res == DW_DLV_OK) {
  307.             ares = dwarf_formaddr(attr,&addr,perr);
  308.             if(ares == DW_DLV_OK) {
  309.               send_addr_note(DW_SECTION_INFO,offset,addr);
  310.             } else if( ares == DW_DLV_ERROR) {
  311.             return ares;
  312.             } /* no entry: ok. */
  313.           } else {
  314.             res = DW_DLV_ERROR; /* NO_ENTRY is impossible.*/
  315.           }
  316.           break;
  317.   
  318.           default:
  319.         /* surprising! An error? */
  320.  
  321.           ; /* do nothing */
  322.           }
  323.           dwarf_dealloc(dbg,attr, DW_DLA_ATTR);
  324.       
  325.         } else {
  326.           res = ares;
  327.         }
  328.    return res;
  329. }
  330.  
  331. /*
  332.     Return DW_DLV_OK if handling this went ok.
  333. */
  334. static int
  335. handle_attr_locdesc(Dwarf_Debug dbg,Dwarf_Die die,Dwarf_Half attrnum,
  336.     Dwarf_Error*perr)
  337. {
  338.     int retval = DW_DLV_OK;
  339.     Dwarf_Attribute attr;
  340.     Dwarf_Locdesc *llbuf;
  341.     Dwarf_Signed i;
  342.     Dwarf_Off offset;
  343.     Dwarf_Loc *locp;
  344.     unsigned int entindx;
  345.     int res;
  346.     int ares;
  347.  
  348.  
  349.         ares = dwarf_attr(die,attrnum,&attr,perr);
  350.         if(ares == DW_DLV_OK) {
  351.           Dwarf_Half form ;
  352.           int fres =  dwarf_whatform(attr,&form,perr);
  353.           if(fres == DW_DLV_OK) {
  354.             switch(form) {
  355.             case DW_FORM_block1:
  356.             case DW_FORM_block2:
  357.             case DW_FORM_block4:
  358.           /* must be location description */
  359.           res = dwarf_attr_offset(die,attr,&offset,perr);
  360.           llbuf = 0;
  361.           if(res == DW_DLV_OK) {
  362.             Dwarf_Signed count;
  363.             int lres =  dwarf_loclist(attr,&llbuf,&count,perr);
  364.             if(lres != DW_DLV_OK) {
  365.             return lres;
  366.             }
  367.             if(count != 1) {
  368.             /* this cannot happen! */
  369.             /* perr? */
  370.             _dwarf_error(dbg,perr,DW_DLE_LOCDESC_COUNT_WRONG);
  371.             retval = DW_DLV_ERROR;
  372.             return retval;
  373.             }
  374.             for(i = 0; i < count; ++i) {
  375.             unsigned int ents = llbuf[i].ld_cents;
  376.             locp = llbuf[i].ld_s;
  377.             for(entindx = 0; entindx < ents; entindx++) {
  378.               Dwarf_Loc *llocp;
  379.               llocp = locp + entindx;
  380.               if (llocp->lr_atom == DW_OP_addr) {
  381.                        send_addr_note(DW_SECTION_INFO,offset+
  382.                 llocp->lr_offset,llocp->lr_number);
  383.               }
  384.             }
  385.             }
  386.  
  387.  
  388.             if(count > 0) {
  389.                 for(i = 0; i < count; ++i) {
  390.                 dwarf_dealloc(dbg,llbuf[i].ld_s,DW_DLA_LOC_BLOCK);
  391.                     }
  392.             dwarf_dealloc(dbg,llbuf,DW_DLA_LOCDESC);
  393.             }
  394.           } else {
  395.             retval =  res;
  396.               }
  397.           break;
  398.                   
  399.             default:
  400.           /* must be a const offset in debug_loc */
  401.           ; /* do nothing */
  402.             }
  403.             dwarf_dealloc(dbg,attr, DW_DLA_ATTR);
  404.          } /* else error or no entry */
  405.          retval = fres;
  406.         } else {
  407.           retval = ares;
  408.         }
  409.    return retval;
  410. }
  411.  
  412. /*
  413.   Return DW_DLV_OK, or DW_DLV_ERROR
  414.  
  415.   Handle the addrs in a single die.
  416. */
  417. static int
  418. process_this_die_attrs(Dwarf_Debug dbg,Dwarf_Die newdie,int *errval)
  419. {
  420.     Dwarf_Error err;
  421.     Dwarf_Half i;
  422.     Dwarf_Half newattrnum;
  423.     Dwarf_Block *blk;
  424.     Dwarf_Off offset;
  425.     Dwarf_Attribute attr;
  426.     int res;
  427.     int tres;
  428.     Dwarf_Half ltag;
  429.  
  430.     Dwarf_Off doff;
  431.     int doffres = dwarf_dieoffset(newdie,&doff,&err);
  432.     if(doffres != DW_DLV_OK) {
  433.        if(doffres ==DW_DLV_ERROR) {
  434.         *errval = dwarf_errno(err);
  435.        }
  436.        return doffres;
  437.     }
  438.         tres = dwarf_tag(newdie,<ag,&err);
  439.     if(tres != DW_DLV_OK) {
  440.         return tres;
  441.     }
  442.     if(DW_TAG_compile_unit == ltag) {
  443.        /* because of the way the dwarf_line code works, we
  444.        ** do lines only per compile unit.
  445.        ** This may turn out to be wrong if we have lines
  446.        ** left unconnected to a CU.
  447.        ** of course such lines will not, at present, be
  448.        ** used by gnome
  449.        ** This is not ideal as coded due to the dwarf_line.c issue.
  450.        */
  451.        int lres;
  452.            lres = handle_debug_line(dbg, newdie,
  453.                  send_addr_note,errval);
  454.        if(lres == DW_DLV_ERROR) {
  455.         return lres;
  456.        }
  457.     }
  458.  
  459.     for(i=0;i < sizeof(might_have_addr)/sizeof(int);i++){
  460.       int resattr;
  461.       Dwarf_Bool hasattr;
  462.       newattrnum = might_have_addr[i];
  463.       err = 0;
  464.       resattr = dwarf_hasattr(newdie,newattrnum,&hasattr,&err);
  465.       if(DW_DLV_OK == resattr) {
  466.         if(hasattr) {
  467.           res = handle_attr_addr(dbg,newdie,newattrnum,&err);
  468.           if(res != DW_DLV_OK) {
  469.             *errval = dwarf_errno(err);
  470.             return DW_DLV_ERROR;
  471.           }
  472.         }
  473.       } else {
  474.         if(resattr == DW_DLV_ERROR) {
  475.             *errval = dwarf_errno(err);
  476.         return resattr;
  477.         }
  478.       }
  479.     }
  480.     for(i=0;i < sizeof(might_have_locdesc)/sizeof(int);i++){
  481.       int resattr;
  482.       Dwarf_Bool hasattr;
  483.       newattrnum = might_have_locdesc[i];
  484.       err = 0;
  485.       resattr = dwarf_hasattr(newdie,newattrnum,&hasattr,&err);
  486.       if(DW_DLV_OK == resattr) {
  487.         if(hasattr) {
  488.           res = handle_attr_locdesc(dbg,newdie,newattrnum,&err);
  489.           if(res != DW_DLV_OK) {
  490.             *errval = dwarf_errno(err);
  491.             return DW_DLV_ERROR;
  492.           }
  493.         }
  494.       } else {
  495.         if(resattr == DW_DLV_ERROR) {
  496.             *errval = dwarf_errno(err);
  497.         return resattr;
  498.         }
  499.       }
  500.     }
  501.  
  502.     return DW_DLV_OK;
  503. }
  504.  
  505. /*
  506.     Handle siblings as a list,
  507.     Do children by recursing.
  508.     Effectively this is walking the tree preorder.
  509.  
  510.     This dealloc's any die passed to it, so the
  511.     caller should not do that dealloc.
  512.     It seems more logical to have the one causing
  513.     the alloc to do the dealloc, but that way this
  514.     routine became a mess.
  515.  
  516. */
  517. static int 
  518. do_this_die_and_dealloc(Dwarf_Debug dbg,Dwarf_Die die,int *errval)
  519. {
  520.  
  521.     Dwarf_Die prevdie = 0;
  522.     Dwarf_Die newdie = die;
  523.     Dwarf_Error err = 0;
  524.     int res = 0;
  525.     int first = 1;
  526.     int sibres = DW_DLV_OK;
  527.     int tres = DW_DLV_OK;
  528.     Dwarf_Die sibdie;
  529.  
  530.     while (sibres == DW_DLV_OK) {
  531.         Dwarf_Die ch_die;
  532.  
  533.  
  534.         res = process_this_die_attrs(dbg,newdie,errval);
  535.         switch(res) {
  536.         case DW_DLV_OK:
  537.             break;
  538.         case DW_DLV_NO_ENTRY:
  539.             break;
  540.         default:
  541.         case DW_DLV_ERROR:
  542.                     if(prevdie) {
  543.                        dwarf_dealloc(dbg,prevdie,DW_DLA_DIE);
  544.                        prevdie = 0;
  545.                     }
  546.             return DW_DLV_ERROR;
  547.         }
  548.  
  549.         tres  = dwarf_child(newdie,&ch_die,&err);
  550.        
  551.         if(tres == DW_DLV_OK ) {
  552.            res = do_this_die_and_dealloc(dbg,ch_die,errval);
  553.                switch(res) {
  554.                case DW_DLV_OK:
  555.             break;
  556.                case DW_DLV_NO_ENTRY:
  557.             break;
  558.                default:
  559.                case DW_DLV_ERROR:
  560.                     if(prevdie) {
  561.                        dwarf_dealloc(dbg,prevdie,DW_DLA_DIE);
  562.                        prevdie = 0;
  563.                     }
  564.             return DW_DLV_ERROR;
  565.                }
  566.         } else if (tres  == DW_DLV_ERROR) {
  567.         /* An error!
  568.         */
  569.             *errval = dwarf_errno(err);
  570.             if(prevdie) {
  571.                   dwarf_dealloc(dbg,prevdie,DW_DLA_DIE);
  572.                   prevdie = 0;
  573.             }
  574.         dwarf_dealloc(dbg,err,DW_DLA_ERROR);
  575.         return DW_DLV_ERROR;
  576.         } /* else was NO ENTRY */
  577.         prevdie = newdie;
  578.         sibdie = 0;
  579.         sibres = dwarf_siblingof(dbg,newdie,&sibdie,&err);
  580.         if(prevdie) {
  581.           dwarf_dealloc(dbg,prevdie,DW_DLA_DIE);
  582.           prevdie = 0;
  583.         }
  584.         newdie = sibdie;
  585.         
  586.     }
  587.     if(sibres  == DW_DLV_NO_ENTRY) {
  588.        return DW_DLV_OK;
  589.       }
  590.     /*error. */
  591.     *errval = dwarf_errno(err);
  592.     if(prevdie) {
  593.           dwarf_dealloc(dbg,prevdie,DW_DLA_DIE);
  594.           prevdie = 0;
  595.     }
  596.     dwarf_dealloc(dbg,err,DW_DLA_ERROR);
  597.     return DW_DLV_ERROR;
  598.  
  599. }
  600.  
  601.  
  602. static int 
  603. handle_debug_frame(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval)
  604. {
  605.   int retval = DW_DLV_OK;
  606.   int res;
  607.   Dwarf_Error err;
  608.   Dwarf_Addr  *addrlist;
  609.   Dwarf_Off  *offsetlist;
  610.   Dwarf_Signed count;
  611.   int i;
  612.  
  613.   res = _dwarf_frame_address_offsets(dbg,&addrlist,&offsetlist,&count,&err);
  614.   if(res == DW_DLV_OK) {
  615.      for(i = 0; i < count; i++) {
  616.         cb_func(DW_SECTION_FRAME,offsetlist[i],addrlist[i]);
  617.      }
  618.      dwarf_dealloc(dbg,offsetlist,DW_DLA_ADDR);
  619.      dwarf_dealloc(dbg,addrlist,DW_DLA_ADDR);
  620.   } else if (res == DW_DLV_NO_ENTRY) {
  621.         retval = res;
  622.   } else {
  623.         *errval = dwarf_errno(err);
  624.         retval = DW_DLV_ERROR;
  625.   }
  626.   return retval;
  627.  
  628. }
  629. static int 
  630. handle_debug_aranges(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval)
  631. {
  632.   int retval = DW_DLV_OK;
  633.   Dwarf_Error err;
  634.   Dwarf_Addr  *aranges;
  635.   Dwarf_Signed count;
  636.   int indx;
  637.   Dwarf_Addr addr;
  638.   Dwarf_Off *offsets;
  639.  
  640.   retval = _dwarf_get_aranges_addr_offsets(dbg,&aranges,&offsets,&count,&err);
  641.   if(retval == DW_DLV_OK) {
  642.     if(count == 0) {
  643.       retval = DW_DLV_NO_ENTRY;
  644.     } else {
  645.      for(indx = 0; indx < count; indx++) {
  646.         cb_func(DW_SECTION_ARANGES,offsets[indx],aranges[indx]);
  647.      }
  648.     }
  649.     dwarf_dealloc(dbg,aranges,DW_DLA_ADDR);
  650.     dwarf_dealloc(dbg,offsets,DW_DLA_ADDR);
  651.   } else if(retval == DW_DLV_NO_ENTRY) {
  652.     ; /* do nothing */
  653.   } else {
  654.     *errval = dwarf_errno(err);
  655.     retval =  DW_DLV_ERROR;
  656.   }
  657.   return retval;
  658. }
  659. static int 
  660. handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
  661.    Dwarf_addr_callback_func cb_func,int *errval)
  662. {
  663.   int retval = DW_DLV_OK;
  664.   int res;
  665.   Dwarf_Error err;
  666.   Dwarf_Addr  *addrlist;
  667.   Dwarf_Off  *offsetlist;
  668.   Dwarf_Unsigned count;
  669.   Dwarf_Unsigned i;
  670.  
  671.   res = _dwarf_line_address_offsets(dbg,cu_die,&addrlist,&offsetlist,&count,&err);
  672.   if(res == DW_DLV_OK) {
  673.      for(i = 0; i < count; i++) {
  674.     cb_func(DW_SECTION_LINE,offsetlist[i],addrlist[i]);
  675.  
  676.      }
  677.      dwarf_dealloc(dbg,offsetlist,DW_DLA_ADDR);
  678.      dwarf_dealloc(dbg,addrlist,DW_DLA_ADDR);
  679.   } else if (res == DW_DLV_NO_ENTRY) {
  680.     retval = res;
  681.   } else {
  682.     *errval = dwarf_errno(err);
  683.     retval = DW_DLV_ERROR;
  684.   }
  685.   return retval;
  686. }
  687.  
  688. /*
  689.     We need to add support for this. Currently we do not
  690.     generate this section.
  691. */
  692. static int 
  693. handle_debug_loc(Dwarf_Debug dbg,Dwarf_addr_callback_func cb_func,int *errval)
  694. {
  695.   int retval = DW_DLV_NO_ENTRY;
  696.   return retval;
  697. }
  698.